package ru.susu.algebra.belonogov;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import ru.susu.algebra.pair.Pair;
import ru.susu.algebra.partition.Partition;
import ru.susu.algebra.partition.PartitionsFactory;
import ru.susu.algebra.partition.filter.NotAlternatingPartitionsFilter;

/**
 * @author akargapolov
 * @since: 06.06.2009
 */
public class ProportionalCharactersSnNAnViewer extends ProportionalCharactersViewerBase
{

	Map<Integer, List<Pair<Partition, Partition>>> nanPartitions = new LinkedHashMap<Integer, List<Pair<Partition, Partition>>>();

	@Override
	protected void createPartitions() throws Exception
	{
		for (int i = 1; i <= MAX_VALUE; i++)
		{
			nanPartitions.put(i, new ArrayList<Pair<Partition, Partition>>());
		}

		//вроде как покрывает все до 100
		int limits[] = new int[]{14,12,10, 7, 3, 3};
		for (int k = 0; k < 6; k++)
		//0 + 7 + 15 + 23 + 31 + 39 = 115 если только k
		{
			for (int m = 0; m < limits[k]; m++)
			//
			{
				if (m > 0)
				{
					add1Pair(k, m);
				}

				add2Pair(k, m);

				if (m < 9 - k)
				{
					add3Pair(k, m);
				}
			}
		}
	}

	@Override
	protected void writePartitions() throws Exception
	{
		MapListsPartitionsWriter writer = new MapListsPartitionsWriter();
		writer.write(nanPartitions, new NotAlternatingPartitionsFilter(), "ExecuteResults/SnNAn/");
	}

	protected Pair<Partition, Partition> add1Pair(int k, int m)
	{
		Integer[] array = new Integer[0];

		Partition p1 = PartitionsFactory.createPartition(array);
		p1 = deltaOp.performOperation(m);
		p1 = addBasePower(p1, 3, k);
		p1 = addOp.performOperation(p1, 4);

		Partition p2 = PartitionsFactory.createPartition(array);
		p2 = deltaOp.performOperation(m);
		p2 = addBasePower(p2, 3, k);

		Integer[] tmp = p2.getArrayRepresentation();
		p2 = increaseOp.performOperation(p2, tmp.length - k - 1, 2);
		p2 = increaseOp.performOperation(p2, tmp.length - k - 2, 2);

		if (p2.getPresentedNumber() > MAX_VALUE)
		{
			return null;
		}

		Pair<Partition, Partition> pair = new Pair<Partition, Partition>(p1, p2);
		nanPartitions.get(p1.getPresentedNumber()).add(pair);
		return pair;
	}

	protected Pair<Partition, Partition> add2Pair(int k, int m)
	{
		Integer[] array = new Integer[0];

		Partition p1 = PartitionsFactory.createPartition(array);
		p1 = sumOp.performOperation(m);
		p1 = addBasePower(p1, 3, k);
		p1 = addOp.performOperation(p1, 4);

		Partition p2 = PartitionsFactory.createPartition(array);
		p2 = sumOp.performOperation(m);
		p2 = addBasePower(p2, 3, k);

		Integer[] tmp = p2.getArrayRepresentation();
		p2 = increaseOp.performOperation(p2, tmp.length - k - 1, 3);
		p2 = increaseOp.performOperation(p2, tmp.length - k - 2, 1);

		if (p2.getPresentedNumber() > MAX_VALUE)
		{
			return null;
		}

		Pair<Partition, Partition> pair = new Pair<Partition, Partition>(p1, p2);
		nanPartitions.get(p1.getPresentedNumber()).add(pair);
		return pair;
	}

	protected Pair<Partition, Partition> add3Pair(int k, int m)
	{
		Integer[] array = new Integer[0];

		Partition p1 = PartitionsFactory.createPartition(array);
		p1 = sumOp.performOperation(m);
		p1 = addBasePower(p1, 2, 1);
		p1 = addBasePower(p1, 3, k);
		p1 = addOp.performOperation(p1, 4);

		Partition p2 = PartitionsFactory.createPartition(array);
		p2 = sumOp.performOperation(m);
		p2 = addBasePower(p2, 2, 1);
		p2 = addBasePower(p2, 3, k);

		Integer[] tmp = p2.getArrayRepresentation();
		p2 = increaseOp.performOperation(p2, tmp.length - k - 1, 1);
		p2 = increaseOp.performOperation(p2, tmp.length - k - 2, 3);

		if (p2.getPresentedNumber() > MAX_VALUE)
		{
			return null;
		}

		Pair<Partition, Partition> pair = new Pair<Partition, Partition>(p1, p2);
		nanPartitions.get(p1.getPresentedNumber()).add(pair);
		return pair;
	}

}
